#!/usr/bin/env python3
# -*- coding: utf-8 -*-

"""
日志管理工具
提供日志轮转、清理和统计功能
"""

import os
import sys
import argparse
import json
from datetime import datetime
from typing import Dict, Any, List

# 添加项目根目录到路径
sys.path.append(os.path.join(os.path.dirname(os.path.dirname(__file__)), 'config'))

try:
    from unified_logger import get_logger, LogLevel, LogFormat
    UNIFIED_LOGGER_AVAILABLE = True
except ImportError:
    UNIFIED_LOGGER_AVAILABLE = False
    import logging


class LogManager:
    """日志管理器"""
    
    def __init__(self, log_dir: str = None):
        """
        初始化日志管理器
        
        Args:
            log_dir: 日志目录路径
        """
        self.log_dir = log_dir or os.path.join(os.path.dirname(os.path.dirname(__file__)), 'logs')
        self.setup_logging()
    
    def setup_logging(self):
        """设置日志记录"""
        if UNIFIED_LOGGER_AVAILABLE:
            log_config = {
                'log_level': LogLevel.INFO.value,
                'log_format': LogFormat.DETAILED.value,
                'enable_console': True,
                'enable_file': True,
                'log_dir': self.log_dir,
                'log_filename': 'log_manager.log'
            }
            self.logger = get_logger("log_manager", log_config)
        else:
            logging.basicConfig(
                level=logging.INFO,
                format='%(asctime)s - %(name)s - %(levelname)s - %(message)s'
            )
            self.logger = logging.getLogger('log_manager')
    
    def rotate_logs(self, max_size_mb: int = 10, backup_count: int = 5) -> Dict[str, Any]:
        """
        轮转日志文件
        
        Args:
            max_size_mb: 单个日志文件最大大小(MB)
            backup_count: 保留的备份文件数量
        
        Returns:
            轮转结果统计
        """
        result = {
            'rotated_files': [],
            'total_rotated': 0,
            'errors': []
        }
        
        if not os.path.exists(self.log_dir):
            self.logger.warning(f"日志目录不存在: {self.log_dir}")
            return result
        
        max_size_bytes = max_size_mb * 1024 * 1024
        
        try:
            for filename in os.listdir(self.log_dir):
                if not filename.endswith('.log'):
                    continue
                
                file_path = os.path.join(self.log_dir, filename)
                
                try:
                    if os.path.getsize(file_path) > max_size_bytes:
                        # 执行轮转
                        self._rotate_single_file(file_path, backup_count)
                        result['rotated_files'].append(filename)
                        result['total_rotated'] += 1
                        
                except Exception as e:
                    error_msg = f"轮转文件 {filename} 失败: {e}"
                    result['errors'].append(error_msg)
                    self.logger.error(error_msg)
            
            if result['total_rotated'] > 0:
                self.logger.info(f"成功轮转 {result['total_rotated']} 个日志文件")
            
        except Exception as e:
            error_msg = f"轮转日志时出错: {e}"
            result['errors'].append(error_msg)
            self.logger.error(error_msg)
        
        return result
    
    def _rotate_single_file(self, file_path: str, backup_count: int):
        """轮转单个文件"""
        base_name = file_path
        
        # 移动现有备份文件
        for i in range(backup_count - 1, 0, -1):
            old_backup = f"{base_name}.{i}"
            new_backup = f"{base_name}.{i + 1}"
            
            if os.path.exists(old_backup):
                if i == backup_count - 1:
                    # 删除最老的备份
                    os.remove(old_backup)
                else:
                    os.rename(old_backup, new_backup)
        
        # 将当前文件重命名为 .1
        if os.path.exists(file_path):
            os.rename(file_path, f"{base_name}.1")
    
    def clean_old_logs(self, days_to_keep: int = 7) -> Dict[str, Any]:
        """
        清理旧日志文件
        
        Args:
            days_to_keep: 保留的天数
        
        Returns:
            清理结果统计
        """
        result = {
            'cleaned_files': [],
            'total_cleaned': 0,
            'total_size_freed_mb': 0,
            'errors': []
        }
        
        if not os.path.exists(self.log_dir):
            self.logger.warning(f"日志目录不存在: {self.log_dir}")
            return result
        
        cutoff_time = datetime.now().timestamp() - (days_to_keep * 24 * 60 * 60)
        
        try:
            for filename in os.listdir(self.log_dir):
                if not (filename.endswith('.log') or '.log.' in filename):
                    continue
                
                file_path = os.path.join(self.log_dir, filename)
                
                try:
                    file_stat = os.stat(file_path)
                    if file_stat.st_mtime < cutoff_time:
                        file_size_mb = file_stat.st_size / (1024 * 1024)
                        os.remove(file_path)
                        
                        result['cleaned_files'].append({
                            'name': filename,
                            'size_mb': round(file_size_mb, 2),
                            'age_days': round((datetime.now().timestamp() - file_stat.st_mtime) / (24 * 60 * 60), 1)
                        })
                        result['total_cleaned'] += 1
                        result['total_size_freed_mb'] += file_size_mb
                        
                except Exception as e:
                    error_msg = f"清理文件 {filename} 失败: {e}"
                    result['errors'].append(error_msg)
                    self.logger.error(error_msg)
            
            result['total_size_freed_mb'] = round(result['total_size_freed_mb'], 2)
            
            if result['total_cleaned'] > 0:
                self.logger.info(f"清理了 {result['total_cleaned']} 个旧日志文件，释放空间 {result['total_size_freed_mb']} MB")
            
        except Exception as e:
            error_msg = f"清理旧日志时出错: {e}"
            result['errors'].append(error_msg)
            self.logger.error(error_msg)
        
        return result
    
    def get_log_statistics(self) -> Dict[str, Any]:
        """获取日志统计信息"""
        stats = {
            'log_dir': self.log_dir,
            'total_files': 0,
            'total_size_mb': 0,
            'files_by_type': {},
            'largest_files': [],
            'oldest_files': [],
            'newest_files': []
        }
        
        if not os.path.exists(self.log_dir):
            return stats
        
        try:
            files_info = []
            
            for filename in os.listdir(self.log_dir):
                if not (filename.endswith('.log') or '.log.' in filename or filename.endswith('.json')):
                    continue
                
                file_path = os.path.join(self.log_dir, filename)
                
                try:
                    file_stat = os.stat(file_path)
                    size_mb = file_stat.st_size / (1024 * 1024)
                    
                    file_info = {
                        'name': filename,
                        'size_mb': round(size_mb, 2),
                        'modified': datetime.fromtimestamp(file_stat.st_mtime).isoformat(),
                        'age_days': round((datetime.now().timestamp() - file_stat.st_mtime) / (24 * 60 * 60), 1)
                    }
                    
                    files_info.append(file_info)
                    stats['total_size_mb'] += size_mb
                    
                    # 按文件类型分类
                    if filename.endswith('.json'):
                        file_type = 'json'
                    elif '.log.' in filename:
                        file_type = 'rotated_log'
                    else:
                        file_type = 'current_log'
                    
                    if file_type not in stats['files_by_type']:
                        stats['files_by_type'][file_type] = {'count': 0, 'size_mb': 0}
                    
                    stats['files_by_type'][file_type]['count'] += 1
                    stats['files_by_type'][file_type]['size_mb'] += size_mb
                    
                except Exception as e:
                    self.logger.warning(f"无法获取文件 {filename} 的统计信息: {e}")
            
            stats['total_files'] = len(files_info)
            stats['total_size_mb'] = round(stats['total_size_mb'], 2)
            
            # 排序并获取前5个
            files_info.sort(key=lambda x: x['size_mb'], reverse=True)
            stats['largest_files'] = files_info[:5]
            
            files_info.sort(key=lambda x: x['age_days'], reverse=True)
            stats['oldest_files'] = files_info[:5]
            
            files_info.sort(key=lambda x: x['age_days'])
            stats['newest_files'] = files_info[:5]
            
            # 四舍五入文件类型统计
            for file_type in stats['files_by_type']:
                stats['files_by_type'][file_type]['size_mb'] = round(stats['files_by_type'][file_type]['size_mb'], 2)
            
        except Exception as e:
            self.logger.error(f"获取日志统计信息时出错: {e}")
        
        return stats
    
    def maintenance(self, max_size_mb: int = 10, backup_count: int = 5, days_to_keep: int = 7) -> Dict[str, Any]:
        """
        执行日志维护（轮转 + 清理）
        
        Args:
            max_size_mb: 单个日志文件最大大小(MB)
            backup_count: 保留的备份文件数量
            days_to_keep: 保留的天数
        
        Returns:
            维护结果统计
        """
        self.logger.info("开始执行日志维护...")
        
        result = {
            'rotation_result': {},
            'cleanup_result': {},
            'before_stats': {},
            'after_stats': {},
            'maintenance_time': datetime.now().isoformat()
        }
        
        # 获取维护前统计
        result['before_stats'] = self.get_log_statistics()
        
        # 执行轮转
        result['rotation_result'] = self.rotate_logs(max_size_mb, backup_count)
        
        # 执行清理
        result['cleanup_result'] = self.clean_old_logs(days_to_keep)
        
        # 获取维护后统计
        result['after_stats'] = self.get_log_statistics()
        
        self.logger.info("日志维护完成")
        return result


def main():
    """主函数"""
    parser = argparse.ArgumentParser(description='日志管理工具')
    parser.add_argument('--log-dir', help='日志目录路径')
    parser.add_argument('--action', choices=['rotate', 'clean', 'stats', 'maintenance'], 
                       default='stats', help='执行的操作')
    parser.add_argument('--max-size', type=int, default=10, help='单个日志文件最大大小(MB)')
    parser.add_argument('--backup-count', type=int, default=5, help='保留的备份文件数量')
    parser.add_argument('--days-to-keep', type=int, default=7, help='保留的天数')
    parser.add_argument('--output-format', choices=['json', 'text'], default='text', help='输出格式')
    
    args = parser.parse_args()
    
    # 创建日志管理器
    log_manager = LogManager(args.log_dir)
    
    # 执行操作
    if args.action == 'rotate':
        result = log_manager.rotate_logs(args.max_size, args.backup_count)
    elif args.action == 'clean':
        result = log_manager.clean_old_logs(args.days_to_keep)
    elif args.action == 'stats':
        result = log_manager.get_log_statistics()
    elif args.action == 'maintenance':
        result = log_manager.maintenance(args.max_size, args.backup_count, args.days_to_keep)
    
    # 输出结果
    if args.output_format == 'json':
        print(json.dumps(result, indent=2, ensure_ascii=False))
    else:
        print(f"\n=== 日志管理结果 ({args.action}) ===")
        if args.action == 'stats':
            print(f"日志目录: {result['log_dir']}")
            print(f"总文件数: {result['total_files']}")
            print(f"总大小: {result['total_size_mb']} MB")
            print(f"文件类型分布: {result['files_by_type']}")
        else:
            print(json.dumps(result, indent=2, ensure_ascii=False))


if __name__ == "__main__":
    main()